package com.mscsoft.musicscore;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.mscsoft.musicscore.note.Note;

/** 一个谱面 */
public class MusicScore {
    public final double bpm;
    public final Meta meta;
    public final List<Note> notes;
    public final Sound sound;

    public MusicScore(double bpm, Meta meta, List<Note> notes, Sound sound) {
        this.bpm = bpm;
        this.meta = meta;
        this.notes = notes;
        this.sound = sound;
    }

    /** 读写谱面工具 */
    public static class Tools {
        // 读谱面
        public static MusicScore readFromFile(String pathname) throws IOException {
            return readFromFile(new File(pathname));
        }

        public static MusicScore readFromFile(File file) throws IOException {
            return readFromInputStream(new FileInputStream(file));
        }

        public static MusicScore readFromInputStream(InputStream inputStream) throws IOException {
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
                StringBuilder sb = new StringBuilder();
                for (int i = reader.read(); i != -1; i = reader.read()) {
                    sb.append((char) i);
                }
                return readFromJSON(sb.toString());
            }
        }

        public static MusicScore readFromJSON(String text) {
            return JSON.parseObject(text, MusicScore.class);
        }

        // 写谱面
        public static void writeToFile(String pathname, MusicScore ms) throws IOException {
            writeToFile(new File(pathname), ms);
        }

        public static void writeToFile(File file, MusicScore ms) throws IOException {
            try (BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
                writer.write(JSON.toJSONString(ms, true));
                writer.flush();
            }
        }

        private Tools() {
            throw new IllegalStateException("Utility class");
        }
    }

    @Override
    public int hashCode() {
        return (meta == null) ? 0 : meta.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MusicScore other = (MusicScore) obj;
        if (meta == null) {
            if (other.meta != null)
                return false;
        } else if (!meta.equals(other.meta))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "MusicScore [bpm=" + bpm + ", meta=" + meta + ", notes=" + notes.size() + ", sound=" + sound + "]";
    }
}
